package com.aluka.nirvana.framework.core.utils;

import lombok.extern.slf4j.Slf4j;
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;

/**
 * RSA加密工具类
 **/
@Slf4j
public class RSAUtils {
    /** 密钥类型 */
    private static final String KEY_RSA_TYPE = "RSA";
    /** 密钥大小 */
    private static final int KEY_SIZE = 1024;
     /** 编码大小 */
    private static final int ENCODE_PART_SIZE = KEY_SIZE / 8;
     /** 私钥 */
    private static final String ADMIN_PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKw7ZAuzxeFvda81QJJ6FrUWqE2jrYL0okCbFu3m8OCR3mYBTKBaACa3CeOysBvnm7hIp0h1vVz5/Re8MmLQwi+wEctgm6Pd1HEJtz4Mi5rTtrd55GJx4cKobp4J/KWffG75JbIFgrI+Yt8ygz3lOzyiNGWWk/UjpbemIAFekPChAgMBAAECgYBDiN5IAGwdY7k/xJ/XT+xLgeDo4L+O1CIzNx0cmCvnwwrz8Jp9Xg0lISzNjimkJ4NWFZcSwKhKJvRpNDCFstoRd9zeRH6s6k33KMqsLz4Ksp6097lUc/VoVP0ffssmnFKsGjV7dVN7C4joprJrhwnZeU+ehy92Fx8uB8jSp95bYQJBAOGodf5SzB8kv1iHNRt2rGwY/AHtf0RcLDai+a++Scf3HjxCpdV3N4cUAt2XA3Yq4v6+hROJbh/rDtT0heDH8qUCQQDDY+m48YDEnWO5GVocof3rMskr/gSyVbVDOB8z+8ys2e1eknWdshkKMPQLfj89qML2tfkmRr5/EHWfl1M9EBFNAkA4g3URfXDrd8uIA0yUlTL3W4Z5gR43Y5IbGNPJZLGbp9LlqpdXj6TTanqRPkm6pWD2BYbUbr2qtrafNKH2unyVAkEAhvU1E5Rj/+pCXjCfqFVPwKwEfglnjxJaMELMcqiCmAWyyfbZnIHOf9aOSn36ConNmIDaxdBpdfSVehUY3n2BpQJBAJOzI/b/6X1sMh35oK0Ezfk4K3vN8ELRHBgg70ei1PaTXVSknbEBkciSj79ZH1MnE6rS0Z3Zao+IpCSp+zKHxLU=";
     /** 公钥 */
    private static final String ADMIN_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsO2QLs8Xhb3WvNUCSeha1FqhNo62C9KJAmxbt5vDgkd5mAUygWgAmtwnjsrAb55u4SKdIdb1c+f0XvDJi0MIvsBHLYJuj3dRxCbc+DIua07a3eeRiceHCqG6eCfyln3xu+SWyBYKyPmLfMoM95Ts8ojRllpP1I6W3piABXpDwoQIDAQAB";

    /**
     * 创建密钥
     *
     */
    public static Map<String, String> createRsaKeys() {
        Map<String, String> keyPairMap = new HashMap<>();
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_RSA_TYPE);
            keyPairGenerator.initialize(KEY_SIZE, new SecureRandom());
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            String publicKeyValue = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
            String privateKeyValue = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
            log.info("公钥：" + publicKeyValue);
            log.info("私钥：" + privateKeyValue);
        } catch (NoSuchAlgorithmException e) {
            log.warn("创建密钥失败: {}", e.getMessage());
        }
        return keyPairMap;
    }

    /**
     * 平台加密
     *
     * @param sourceStr 源文本
     */
    public static String encode(String sourceStr) {
        byte[] publicBytes = Base64.getDecoder().decode(ADMIN_PUBLIC_KEY);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicBytes);
        List<byte[]> alreadyEncodeListData = new LinkedList<>();
        String encodeBase64Result = null;
        int maxEncodeSize = ENCODE_PART_SIZE - 11;
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE);
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE);
            cipher.init(1, publicKey);
            byte[] sourceBytes = sourceStr.getBytes(StandardCharsets.UTF_8);
            int sourceLen = sourceBytes.length;
            int partLen;
            int curPosition;
            byte[] tempByteList;
            for (partLen = 0; partLen < sourceLen; partLen += maxEncodeSize) {
                curPosition = sourceLen - partLen;
                int tempLen = Math.min(curPosition, maxEncodeSize);
                byte[] tempBytes = new byte[tempLen];
                System.arraycopy(sourceBytes, partLen, tempBytes, 0, tempLen);
                tempByteList = cipher.doFinal(tempBytes);
                alreadyEncodeListData.add(tempByteList);
            }
            partLen = alreadyEncodeListData.size();
            curPosition = partLen * ENCODE_PART_SIZE;
            byte[] encodeData = new byte[curPosition];
            for (int i = 0; i < partLen; ++i) {
                tempByteList = alreadyEncodeListData.get(i);
                System.arraycopy(tempByteList, 0, encodeData, i * ENCODE_PART_SIZE, ENCODE_PART_SIZE);
            }
            encodeBase64Result = Base64.getEncoder().encodeToString(encodeData);
        } catch (Exception var16) {
            var16.printStackTrace();
        }
        return encodeBase64Result;
    }

    /**
     * 平台解密
     *
     * @param sourceBase64Rsa 加密文本
     */
    public static String decode(String sourceBase64Rsa) {
        byte[] privateBytes = Base64.getDecoder().decode(ADMIN_PRIVATE_KEY);
        byte[] encodeSource = Base64.getDecoder().decode(sourceBase64Rsa);
        int encodePartLen = encodeSource.length / ENCODE_PART_SIZE;
        List<byte[]> decodeListData = new LinkedList<>();
        String decodeStrResult = null;
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateBytes);
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE);
            cipher.init(2, privateKey);
            int allDecodeByteLen = 0;
            for (int i = 0; i < encodePartLen; ++i) {
                byte[] tempEncodedData = new byte[ENCODE_PART_SIZE];
                System.arraycopy(encodeSource, i * ENCODE_PART_SIZE, tempEncodedData, 0, ENCODE_PART_SIZE);
                byte[] decodePartData = cipher.doFinal(tempEncodedData);
                decodeListData.add(decodePartData);
                allDecodeByteLen += decodePartData.length;
            }
            byte[] decodeResultBytes = new byte[allDecodeByteLen];
            int i = 0;
            for (int curPosition = 0; i < encodePartLen; ++i) {
                byte[] tempSourceBytes = decodeListData.get(i);
                int tempSourceBytesLen = tempSourceBytes.length;
                System.arraycopy(tempSourceBytes, 0, decodeResultBytes, curPosition, tempSourceBytesLen);
                curPosition += tempSourceBytesLen;
            }
            decodeStrResult = new String(decodeResultBytes, StandardCharsets.UTF_8);
        } catch (Exception var16) {
            var16.printStackTrace();
        }
        return decodeStrResult;
    }

}